package com.ruoyi.demo;

import cn.hutool.core.lang.Console;
import cn.hutool.core.lang.Filter;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import lombok.ToString;
import org.apache.poi.ss.formula.functions.T;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * <简述>
 * <详细描述>
 *
 * @author syf
 * @date 2024年08月19日 14:59
 */
public class TestReflectUtils {



    // Teacher类
    static class Teacher{
        private String name;
        private int age;

        public Teacher() {
        }

        public Teacher(String name, int age) {
            this.name = name;
            this.age = age;
        }
        private  static final String sex = "男";

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public int getAge() {
            return age;
        }

        @Override
        public String toString() {
            return StringUtils.format("Teacher{name={}, age={}}", this.name, this.age);
        }
    }
    public static void main(String[] args) {
       //testReflect();
        // testFieldGet();
        //testConstructor();
        //testInstance();
        //testMethod();
        //testInvoke();

        testGetSet();

    }

    static void  testGetSet(){
        Teacher teacher = new Teacher();
        Console.log("name->invokeGetter方法执行：");
        ReflectUtils.invokeSetter(teacher, "name", "张三");

        String name =  ReflectUtils.invokeGetter(teacher, "name");
        Console.log("name->invokeGetter方法执行：",name);
    }

    /**
     * <简述>invoke
     * <详细描述>
     * @author syf
     * @date 2024/8/20 15:54
     */
    static void  testInvoke(){
        //获取方法 setName
       Method method = ReflectUtils.getMethod(Teacher.class, "setName", String.class);
       Teacher teacher = new Teacher();
       //
       ReflectUtils.invoke(teacher, method, "张三");
       Console.log("invoke->执行toString结果：",teacher);
   }

    /**
     * <简述>反射获取成员方法
     * <详细描述>
     * @author syf
     * @date 2024/8/20 15:43
     */
    static void testMethod(){
        Method[] methods = ReflectUtils.getMethods(Teacher.class);
        for (Method method: methods) {
           if (method.getDeclaringClass().isInstance(Object.class)){
               Console.log("打印OBJECT的方法------------------------------------------------------------------------");
           }
            Console.log("getMethods->获取方法：",method);
        }
        Console.log("testMethod->获取方法：",ReflectUtils.getMethod(Teacher.class, "toString"));
    }

    /**
     * <简述>实例化
     * <详细描述>
     * @author syf
     * @date 2024/8/20 10:57
     */
    static void testInstance(){
        // 获取Teacher类的实例
        Teacher teacher = ReflectUtils.newInstance(Teacher.class);
        Console.log("newInstance->获取Teacher类的实例：",teacher);
        // 获取Teacher类的实例,传入参数
        Teacher teacher1 = ReflectUtils.newInstance(Teacher.class, "张三", 18);
        Console.log("newInstance->获取Teacher类的实例,传入参数：",teacher1);
    }

    /**
     * <简述>构造函数
     * <详细描述>
     * @author syf
     * @date 2024/8/20 10:56
     */
    static void testConstructor(){
        // 获取所有构造方法
        Constructor<Teacher>[] constructors = ReflectUtils.getConstructors(Teacher.class);
        for (Constructor<Teacher> constructor : constructors){
            Console.log("getConstructors->获取构造方法：",constructor);
        }

        // 获取无参构造方法
        Constructor<Teacher> constructor = ReflectUtils.getConstructor(Teacher.class);
        Console.log("getConstructor->获取无参构造方法：",constructor);
        // 获取有参构造方法
        Constructor<Teacher> constructor1 = ReflectUtils.getConstructor(Teacher.class, String.class, int.class);
        Console.log("getConstructor->获取有参构造方法：",constructor1);

        String name = constructor1.getName();
        Console.log("name:{}",name);
        int modifiers = constructor1.getModifiers();
        Console.log("modifiers:{}",modifiers);

    }

    /**
     * <简述>get set 操作
     * <详细描述>
     * @author syf
     * @date 2024/8/19 16:32
     */

    static  void testFieldGet(){
        Field nameField = ReflectUtils.getField(Teacher.class, "name");
        Teacher teacher = new Teacher();
        teacher.setName("张三");
        // 方式1
        try {
            // 设置字段的可访问性,否则私有属性访问不到
            nameField.setAccessible(true);
            String s = (String) nameField.get(teacher);
            Console.log("get() = {}", s);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        //方式2
        String fieldValue = (String) ReflectUtils.getFieldValue(teacher, nameField);
        Console.log("getFieldValue->获取字段值：",fieldValue);
       //方式3
        String fieldValue1 = (String) ReflectUtils.getFieldValue(teacher, "name");
        Console.log("getFieldValue->获取字段值：",fieldValue1);


        //设置值
        ReflectUtils.setFieldValue(teacher, "name", "李四");
        Console.log("setFieldValue->设置字段值：",ReflectUtils.getFieldValue(teacher, "name"));
        ReflectUtils.setFieldValue(teacher, nameField, "王五");
        Console.log("setFieldValue->设置字段值：",ReflectUtils.getFieldValue(teacher, "name"));


        //获取final字段,修改value
        //初始化前先移除 final，否则修改不了
        ReflectUtils.removeFinalModify(ReflectUtils.getField(Teacher.class, "sex"));
        Teacher teacherFinalSex = new Teacher();
        ReflectUtils.setFieldValue(teacherFinalSex, "sex", "女");
        Console.log("setFieldValue->设置字段值：",ReflectUtils.getFieldValue(teacherFinalSex, "sex"));
    }


    /**
     * <简述>反射修改字段
     * <详细描述>
     * @author syf
     * @date 2024/8/19 16:32
     */
    static  void testReflect(){
        // 获取Teacher类的所有字段
        Field[] fields = ReflectUtils.getFields(Teacher.class);
        for (Field field :fields) {
            Console.log("STAR---------------------------------------------------------------");
            Console.log("getFields-获取Teacher类的所有字段：", field);
            // 获取字段名
            Console.log("getFieldName->获取字段名：",ReflectUtils.getFieldName(field));
            // 获取字段值
            Console.log("getFieldValue->获取字段值：",ReflectUtils.getFieldValue(new Teacher(),field));
            // 获取字段修饰符
            Console.log("getModifiers->获取字段修饰符：",field.getModifiers());
            // 获取字段类型
            Console.log("getType->获取字段类型：",field.getType());
            Console.log("END---------------------------------------------------------------\n");
        }

        Console.log("STAR---------------------------------------------------------------");
        // 获取Teacher类的所有字段,返回age字段
        Field[] fields1 = ReflectUtils.getFields(Teacher.class, field -> "age".equals(field.getName()));
        for (Field field :fields1) {
            Console.log("getFields-返回age字段：", field);
        }
        Console.log("END---------------------------------------------------------------\n");

        //获取单个字段
        Field field = ReflectUtils.getField(Teacher.class, "age");
        Console.log("getField-获取单个字段：", field);
    }
}
